import s94_app from "@/js/s94_app.mjs.js";
import s94 from "s94-js";

var download_book = (function (){
    function template_string(template, param){
        return template.replace(/\{\{(\w+?)\}\}/g, function (m0,m1){
            return m1 in param ? param[m1] : m0;
        })
    }
    function innerText(html){
        if (!html) return html;
        let res;
        html = html.replace(/<!--[.\s\S]*?-->/g,''); // 移除注释
        while (res != html){
            html = res || html;
            res = html.replace(/<(\w+)[^>]*>([.\s\S]*?)<\/\1>/ig, function (ms,m1,m2){
                let is_br = ~['p','div'].indexOf(m1);
                return (is_br ? "\n" : "")+m2;
            });
        }
        res = res.replace(/<(\w+)[^>]*>/g, function (ms,m1){
            return m1=='br' ? "\n" : '';
        }); //单标签处理
        res = res.replaceAll('&lt;', '<');
        res = res.replaceAll('&gt;', '>');
        res = res.replaceAll('&nbsp;', ' ');
        return res;
    }
    //去掉html中的特殊字符
    function decode_html(html){
        html = html.replace(/&([^;]+);/g, function (ms,m1){
            let map = {lt:'&lt;', gt:'&gt;', nbsp:' ', asymp:'/', amp:'&'};
            if (m1 in map) return map[m1];
            if (m1[0]=='#'){
                return String.fromCharCode(m1.replace('#','0'));
            }
            return '';
        })
        return html;
    }
    function get_dom(url){
        return new Promise((resolve, reject)=>{
            s94_app.ajax({
                url: url,
                headers: get_dom.headers,
                success: function(html){
                    if (!~html.indexOf('</body>') || !~html.indexOf('</html>')){
                        typeof(fail)=='function' && fail('乱码',html);
                        return;
                    }
                    html = decode_html(html);
                    var dom = document.createElement('html');
                    dom.innerHTML = html;
                    dom.querySelectorAll('script').forEach(function (v){
                        v.parentNode.removeChild(v);
                    });
                    resolve(dom);
                },
                error: function (html){
                    reject('请求出错：'+url);
                }
            })
        })
    }

    /**
     * 小说下载
     * @param {Object} config 配置参数
     * @param {String} config.url 目录页地址，多个用数组
     * @param {String} config.headers 请求使用的消息头对象
     * @param {String} config.title 标题
     * @param {String} config.get_chapter 获取章节列表的方法，接受一个dom参数，返回一个数组[{title: 标题, url: 地址},...]
     * @param {String} config.get_content 获取章节内容的方法，接受一个dom参数，返回一个字符串
     * @param {String} config.save_name 保存文件名，支持变量模板({{}})，可用变量(title)
     * @param {String} config.chapter_type 章节名类型，none无章节名称，index添加章节序号(第x章 章节名)，其他表示原样显示章节名
     * @param {Function} config.progress 下载进度的回调函数，每下载一章完成调用一次，如果返回false，表示暂停下载，并且缓存已下载内容，接受参数({ok:成功数量, count:总数}, {title:章节标题, url:章节内容地址, content:内容})
     * @param {Function} config.success 下载成功的回调函数，接受参数(res)
     * @param {Function} config.error 下载出错的回调函数，接受参数(errmsg)
     */
    function download_book(config){
        config.timeout = config.timeout || 1;
        if (!config.url) return;
        if (typeof(config.url) == 'string') config.url = [config.url];
        let cache_key = config.url[0];
        let host = s94.url(config.url[0]).host;
        let id = '';
        config.url[0].replace(/(\d+)\D*$/, function (ms,m1){ id = m1; })
        //默认的
        get_dom.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
            'Referer': config.url[0],
        }
        if (config.headers) {
            for (const k in config.headers) {
                get_dom.headers[k] = config.headers[k];
            }
        }
        let pgs = {ok:0, count:0};
        config.progress = typeof(config.progress)=='function' ? config.progress : function (){};
        config.success = typeof(config.success)=='function' ? config.success : function (){};
        config.error = typeof(config.error)=='function' ? config.error : function (){};
        let res = s94.cache(cache_key) || {title: config.title, info:'', chapters:[]};

        s94(function (resolve){//第1步、请求目录页
            if (res.chapters.length > 0) return resolve();
            //获取目录页
            s94.each(config.url, {
                each(url) {
                    return get_dom(url).then((dom)=>{
                        config.get_chapter(dom).forEach(function (v) {
                            res.chapters.push({
                                title: innerText(v.title),
                                url: s94.url(v.url, url).href,
                                content: '',
                            })
                        });
                    })
                },
                over(){resolve()}
            })
        }).then(function (){//第2步、遍历下载每个章节内容
            if (!res.chapters.length) throw '章节为空';
            let stop = false, chapter_start = parseInt(config.chapter_start);
            pgs.count = res.chapters.length - chapter_start;
            //请求每一章的内容
            function download_content(row){
                if (row.content) return (++pgs.ok);
                return get_dom(row.url).then((dom)=>{
                    let text = innerText(config.get_content(dom));
                    text = text.replace(/\n\s+/g, "\n").replace(/\n+/g, "\n");
                    row.content = text;
                    ++pgs.ok;
                    stop = stop || (config.progress(pgs, row) === false);
                }).catch((errmsg)=>{
                    console.log(errmsg+'，重新下载 '+row.url);
                    return download_content(row);
                })
            }

            s94.each(res.chapters, {
                limit: 5,
                each: function (row, i) {
                    if (i < chapter_start) return ; //小于开始章节序列的跳过下载
                    if (stop) return false;
                    return download_content(row);
                },
                over: function () {
                    if (pgs.ok != pgs.count) {
                        s94.cache({[cache_key]: res});
                        return config.error('章节未下载完：'+pgs.ok+'/'+pgs.count);
                    }
                    //保存内容到 .book 目录下
                    let save_name = config.save_name || '{{title}}';
                    let title = res.title.replace(/[\s\n\\\/\?\:\<\>\|\"\']+/g, '');
                    let save_dir = config.save_dir || 'cache:///.book';
                    let file_path = save_dir + '/' + template_string(save_name, {title: title, host: host, id: id}) + '.txt';
                    let txt = s94.trim(res.info, "\n") + "\n";
                    let chapter_template = "\n\n{{title}}\n";
                    switch (config.chapter_type) {
                        case 'none': chapter_template = ''; break;
                        case 'index': chapter_template = "\n\n第{{index}}章 {{title}}\n"; break;
                    }
                    s94.each(res.chapters, function (row, i) {
                        if (i < chapter_start) return ; //小于开始章节序列的跳过写入
                        txt += template_string(chapter_template, {title: s94.trim(row.title, "\n"), index: Number(i) + 1});
                        (config.clear_arr || []).forEach(function (v){
                            row.content = row.content.replaceAll(v, '');
                        })
                        txt += s94.trim(row.content, "\n");
                    })
                    api.writeFile({path: file_path, data: txt}, function (ret, err) {
                        if (ret.status) {
                            s94.cache.remove(cache_key); //清理缓存
                            alert('下载完成，保存在：' + file_path);
                        } else {
                            alert('文件写入失败，可以尝试先删除文件：' + file_path)
                        }
                    });
                    config.success(res);
                }
            })
        })
    }

    download_book.auto_config = function(url){
        //默认的
        get_dom.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
            'Referer': url,
        }
        var res = {
            title: '',
            chapters: [],
            chapters_row: {
                title: '',
                content: '',
                content_html: '',
            },
            config: {
                title: '',
                chapter_key: '',
                content_key: '',
            },
            error: '',
        }

        return get_dom(url).then(function (dom){
            res.title = res.config.title = dom.querySelector('title').innerText;
            let body = dom.querySelector('body'), count_map = {}, path_arr = ['BODY'];
            s94.eachloop(body.children, 'children', function (row, k, obj, ks){
                if (ks.length < path_arr.length){
                    path_arr = path_arr.splice(0, ks.length);
                }
                let path = row.nodeName;
                if(row.id) {
                    path += ('#'+row.id);
                }else if(row.className) {
                    path += ('.'+row.className.replaceAll(' ','.'));
                }
                path_arr.push(path);
                let key = path_arr.join('>');
                count_map[key] = count_map[key] || 0;
                count_map[key]++;
                return true;
            })
            let max_a_key = '', max = Object.values(count_map).sort((a,b)=>{return b-a;})[0];
            s94.each(count_map, function (num, key){
                let is_a = />A([.#][^>]+)?$/.test(key); //是否为A标签
                if (max - num < 10 && is_a){
                    max_a_key = key;
                    return false;
                }
            })
            if(!max_a_key) throw '没有找到目录A标签';
            dom.querySelectorAll(max_a_key).forEach(function (row){
                let href = row.getAttribute('href');
                if (!href || href.indexOf('javascript') === 0) return;
                res.chapters.push({
                    title: row.innerText,
                    url: s94.url(href, url).href,
                })
            })
            if (!res.chapters.length) throw '选中的章节数量为0：'+max_a_key;
            res.config.chapter_key = max_a_key;
        }).then(function (){
            let chapters = res.chapters;
            res.chapters_row = chapters[0];
            return get_dom(res.chapters_row.url).then(function (dom){
                let body = dom.querySelector('body'), path_arr = [], dt_count_map = {};
                function loop(node){
                    let key = node.nodeName;
                    if(node.id) {
                        key += ('#'+node.id);
                    }else if(node.className) {
                        key += ('.'+node.className.replaceAll(' ','.'));
                    }
                    path_arr.push(key);
                    let count = node.innerText.replace(/\s/g,'').length;
                    let max_child = {count:0, node:''};
                    s94.each(node.children, function (v, i){
                        let vc = v.innerText.replace(/\s/g,'').length;
                        if (vc > max_child.count){
                            max_child.count = vc;
                            max_child.node = v;
                        }
                    })
                    //如果字数最多的子元素的字数超过了总字数的 一半 ，继续往下探索
                    if (max_child.count > count*0.5) {
                        return loop(max_child.node)
                    }else {
                        return node;
                    }
                }
                let content_dom = loop(body);
                res.config.content_key = path_arr.join('>');
                res.chapters_row.content = content_dom.innerText;
                res.chapters_row.content_html = content_dom.innerHTML;
                return res;
            })
        })
    }

    return download_book;
})();

export default download_book;